package iconSwingStates.Applications_Exemple.Paint;

import fr.lri.swingstates.canvas.CEllipse;
import fr.lri.swingstates.canvas.CPolyLine;
import fr.lri.swingstates.canvas.CRectangle;
import fr.lri.swingstates.canvas.CShape;
import fr.lri.swingstates.canvas.Canvas;
import fr.lri.swingstates.sm.State;
import fr.lri.swingstates.sm.Transition;
import iconSwingStates.Event.EVirtualConPositionEvent;
import iconSwingStates.StateMachine.SMIconStateMachine;
import iconSwingStates.Transitions.TDrag;
import iconSwingStates.Transitions.TPress;
import iconSwingStates.Transitions.TRelease;
import iconSwingStates.Transitions.TransitionOnTag.TPressOnTag;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Point;

import javax.swing.JFrame;
import javax.swing.SwingUtilities;

/**
 * Classe d'exemple permettant le dessin de formes
 * @author uribe - gaget
 *
 */
public class SMDraw extends SMIconStateMachine{
	State init,draw,nothing;
	private CPolyLine line;
	private CRectangle rectangle;
	private CEllipse circle;
	private int type = 1;
	private int brushSize = 1;
	public static final int LINE = 0;
	public static final int RECT = 1;
	public static final int CIRC = 2;
	private int r=0;
	private int g=0;
	private int b=0;
	private int a=0;
	private Color color=new Color(r,g,b,a);
	private double old_x=-1;
	private double old_y=-1;
	private boolean blqY=false;
	private CShape useShape;

	/**
	 * Constructeur par défaut
	 * @param name Le nom de la machine
	 * @param frame La frame
	 * @param c Le canvas
	 */
	public SMDraw(String name, JFrame frame,Canvas c, String[] pointer) {
		super(name,frame,c,pointer);
		init = new State() { 			
			int[] test = {BOOLEAN};
			Transition press = new TPress("startDrawing","mouse1",false,">> draw"){	
				@Override
				public void action() {
				}
			};
			Transition pressOnTag = new TPressOnTag("dontDrawOnTag","mouse1",false,"notDrawable",">>nothing"){};
		};
		draw = new State(){
			//MultiSlot pour le Drag :
			int[] test = {BOOLEAN};
			Transition move = new TDrag("makeDrawing","mouse1",test,false,false){
				public void action() {
					EVirtualConPositionEvent event = getEvent();
					boolean b = event.getValueAsBoolean(0);
					if(b){
						double x = event.getX();
						double y = event.getY();
						updateGraphic(x,y);
					}
				}
			};
			Transition release = new TRelease("finishDrawing","mouse1", false,">> init"){
				public void action() {
					finishGraphic();
					old_x=-1;
					old_y=-1;
				}
			};
		
		};
		nothing = new State(){			
			Transition release = new TRelease("finishDrawing","mouse1", false,">> init"){
				public void action(){System.out.println("prout");}
			};
				};
	}

	/**
	 * Cette méthode définit le type de forme qu'on veut dessiner
	 * @param type
	 */
	public void setForm(int type){
		this.type = type;
	}

	/*
	 * Méthode qui dessine
	 */
	private void updateGraphic(double _x, double _y){
		Point p = new Point((int)Math.round(_x), (int)Math.round(_y));
		SwingUtilities.convertPointFromScreen(p, getCanvas());
		double x = p.getX();
		double y = p.getY();
		if (blqY){y=useShape.getMaxY()+Math.ceil(brushSize/2);};
		color=SMPalette.color;
		type=SMPalette.type;
		brushSize=SMPalette.brush;
		switch(type){
		case LINE:
			if(line != null){
				line.setStroke( new BasicStroke(brushSize));
				line.setOutlinePaint(color);
				line.lineTo(x, y);
				}
			else{
				line = new CPolyLine(x,y);
				line.setFilled(false);
				line.setStroke( new BasicStroke(brushSize));
				line.setOutlinePaint(color);
				getCanvas().addShape(line);
			}
			line.aboveAll();
			line.below(SMPalette.palette);
			break;
		case RECT:
			if(rectangle != null){
				if (old_x==-1 && old_y==-1){
					old_x = x;
					old_y = y;
				}
				
				rectangle.setStroke( new BasicStroke(brushSize));
			if(old_x > x && old_y > y){
					rectangle.setDiagonal(x, y, old_x, old_y);
				}else{
					rectangle.setDiagonal(old_x, old_y, x, y);
				}
			}
			else{
				rectangle = new CRectangle(x,y,0,0);
				rectangle.setStroke( new BasicStroke(brushSize));
				rectangle.setFillPaint(color);
				getCanvas().addShape(rectangle);
			}
			rectangle.aboveAll();
			rectangle.below(SMPalette.palette);
			break;
		case CIRC:
			if(circle != null){
				if (old_x==-1 && old_y==-1){
					old_x = x;
					old_y = y;
				}
				
				circle.setStroke( new BasicStroke(brushSize));
				if(old_x > x && old_y > y){
					circle.setDiagonal(x, y, old_x, old_y);
				}else{
					circle.setDiagonal(old_x, old_y, x, y);
				}
			}
			else{
				circle = new CEllipse(x,y,0,0);
				circle.setStroke( new BasicStroke(brushSize));
				circle.setFillPaint(color);
				getCanvas().addShape(circle);
			}
			circle.aboveAll();
			circle.below(SMPalette.palette);
			break;                  
		}
	}

	/*
	 * Cette méthode supprime  le composant dessiner pour pouvoir en dessiner une autre
	 */
	private void finishGraphic(){
		switch(type){
		case LINE: line=null;break;
		case RECT: rectangle=null; break;
		case CIRC: circle=null; break;
		}
	}

	/**
	 * Cette méthode définit la taille du pinceau
	 * @param size
	 */
	public void setBrush(int size){
		brushSize = size;
	}
	public void setColor(int r, int g, int b, int a){
		color=new Color(r,g,b,a);
	}

	public int getR() {
		return r;
	}

	public void setR(int r) {
		this.r = r;
	}

	public int getG() {
		return g;
	}

	public void setG(int g) {
		this.g = g;
	}

	public int getB() {
		return b;
	}


	public void setB(int b) {
		this.b = b;
	}

	public int getA() {
		return a;
	}
	public void setA(int a) {
		this.a = a;
	}


}